package characters;

import game.GameWindow;

import java.awt.*;
import java.awt.geom.Rectangle2D;
import java.awt.image.BufferedImage;
import java.awt.image.ImageObserver;
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;

public class Fighter {
    public boolean isGrounded() {
        return  isGrounded;
    }

    public int getAttackDamage() {
        return currentState == FighterState.KICK ? kickDamage : attackDamage;
    }

    // 角色状态
    public enum FighterState {
        IDLE, WALK, JUMP, ATTACK, BLOCK, HIT, KO, DASH, KICK,DOWN
    }

    public int getY() {
        return y;
    }

    public int getX() {
        return x;
    }

    // 基础属性
    protected int x, y;
    protected int width = 120;
    protected int height = 180;
    protected int health = 100;
    protected int maxHealth = 100;
    protected boolean facingRight = true;
    public boolean isGrounded = true;
    public String name;

    // 物理属性
    protected int walkSpeed = 4;
    protected int jumpForce = -15;
    protected int gravity = 1;
    protected int yVelocity = 0;
    protected int dashSpeed = 7; // 冲刺速度比普通行走快

    protected boolean isDashing = false;


    // 战斗属性
    protected int attackDamage = 10;
    protected int kickDamage = 12; // 踢腿伤害
    protected Rectangle2D hitBox;
    protected Rectangle2D attackBox;
    protected boolean isInvincible = false;
    protected int downHealthThreshold = 20; // 倒地血量阈值
    protected boolean isDown = false;
    protected long downStartTime;
    protected static final long DOWN_DURATION = 2000; // 倒地持续时间(毫秒)

    // 动画系统
    protected Animation animation;
    protected FighterState currentState = FighterState.IDLE;

    public Fighter(int x, int y) {
        this.x = x;
        this.y = y;
        this.hitBox = new Rectangle2D.Float(x + 10, y + 20, 60, 100);
        this.animation = new Animation();
        loadAnimations();
    }

    protected void loadAnimations() {
        // 由子类实现具体动画加载
    }

    public void update() {
        // 更新物理状态
        updatePhysics();

        // 更新动画状态
        updateAnimationState();

        // 更新碰撞框
        updateHitBoxes();
    }

    private void updatePhysics() {
        if(isDown){  //倒地保护结束，起身
            if( System.currentTimeMillis()-downStartTime>DOWN_DURATION){
                if(Objects.equals(getName(), "八神庵")){
                    if (facingRight) {
                        x-=150;
                    } else {
                        x=x + width-20;
                    }
                }
                isDown=false;
                isInvincible=false;
                changeState(FighterState.IDLE);
            }
        }
        // 重力应用
        if (!isGrounded) {
            yVelocity += gravity;
            y += yVelocity;
            // 地面检测
            if (y >= 200) { // 假设地面在y=400
                y = 200;
                isGrounded = true;
                yVelocity = 0;

                // 落地后从跳跃状态回到站立或行走
                if (currentState == FighterState.JUMP) {
                    changeState(FighterState.IDLE);
                }
            }
        }
        // 冲刺移动逻辑
        if (isDashing) {
            if (facingRight) {
                x += dashSpeed;
            } else {
                x -= dashSpeed;
            }
            // 冲刺持续时间结束后回到站立状态
            if (animation.isAnimationFinished()) {
                isDashing = false;
                changeState(FighterState.IDLE);
            }
        }
    }

    private void updateAnimationState() {
        // 自动从某些状态回到站立状态
        if (animation.isAnimationFinished()) {
            switch (currentState) {
                case ATTACK:
                case KICK:
                case HIT:
                    changeState(FighterState.IDLE);
                    break;
                case KO:
                    // 保持KO状态
                    break;
                case DASH:
                    isDashing = false;
                    changeState(FighterState.IDLE);
                    break;
            }
        }
    }

    private void updateHitBoxes() {
        // 更新受击框
        hitBox.setRect(x + 10, y + 20, 60, 100);

        // 更新攻击框(仅在攻击时有效)
        if (currentState == FighterState.ATTACK|| currentState == FighterState.KICK
                //&& animation.getCurrentState().equals("ATTACK")
           )
        {
            int attackX = facingRight ? x + width - 20 : x - 40;
            int attackWidth = currentState == FighterState.KICK ? 70 : 60; // 踢腿攻击框更长
            attackBox = new Rectangle2D.Float(attackX, y + 30, attackWidth, 60);
        } else {
            attackBox = null;
        }
    }



    public void draw(Graphics2D g2d) {
        BufferedImage frame = animation.getCurrentFrame();
        if (frame == null) return;

        // 获取动画原始尺寸和当前状态
        int originalWidth = frame.getWidth();
        int originalHeight = frame.getHeight();

        // 设置高质量渲染
        g2d.setRenderingHint(RenderingHints.KEY_INTERPOLATION,
                RenderingHints.VALUE_INTERPOLATION_BILINEAR);
        g2d.setComposite(AlphaComposite.SrcOver);

        // 根据不同状态计算绘制尺寸和位置
        float scale = calculateScaleForState(currentState);
        int drawWidth = (int)(originalWidth * scale);
        int drawHeight = (int)(originalHeight * scale);


        // 特殊角色处理（如八神庵）
        if (name.equals("八神庵")) {
            drawIoriSpecial(g2d, frame, drawWidth, drawHeight);
            drawDebugInfo(g2d);
         //   drawHealthBar(g2d);
            return;
        }

        // 通用绘制逻辑
        switch (currentState) {
            case WALK:
            if (facingRight) {
                g2d.drawImage(frame, x, y-20, drawWidth, drawHeight, null);
            } else {
                g2d.drawImage(frame, x + drawWidth, y-20, -drawWidth, drawHeight, null);
            }
            break;
            case KICK:
                if (facingRight) {
                    g2d.drawImage(frame, x-30, y-40, drawWidth, drawHeight, null);
                } else {
                    g2d.drawImage(frame, x + drawWidth-30, y-40, -drawWidth, drawHeight, null);
                }
            break;
            case KO:
            case DOWN:
                if (facingRight) {
                    g2d.drawImage(frame, x-50, y, drawWidth, drawHeight, null);
                } else {
                    g2d.drawImage(frame, x + drawWidth-50, y, -drawWidth, drawHeight, null);
                }
                break;
            default:
                if (facingRight) {
                    g2d.drawImage(frame, x, y, drawWidth, drawHeight, null);
                } else {
                    g2d.drawImage(frame, x + drawWidth, y, -drawWidth, drawHeight, null);
                }
        }
        drawDebugInfo(g2d);
     //   drawHealthBar(g2d);
    }


    private void drawIoriSpecial(Graphics2D g2d, BufferedImage frame, int width, int height) {
        // 八神庵特殊绘制逻辑
        switch (currentState) {
            case ATTACK:
                if (facingRight) {
                    g2d.drawImage(frame, x - 70, y - 20, width , height , null);
                } else {
                    g2d.drawImage(frame, x + width - 70, y - 20, -width , height , null);
                }
                break;
            case KICK:
                if (facingRight) {
                    g2d.drawImage(frame, x - 35, y-50 , width , height , null);
                } else {
                    g2d.drawImage(frame, x + width - 35, y-50 , -width , height , null);
                }
                break;
            case DOWN:
            case KO:
                if (facingRight) {
                    g2d.drawImage(frame, x-150, y-140, width , height, null);
                } else {
                    g2d.drawImage(frame, x + width-20, y-140, -width , height, null);
                }
                break;
            case HIT:
                if (facingRight) {
                    g2d.drawImage(frame, x-150, y-130, width , height , null);
                } else {
                    g2d.drawImage(frame, x -20+ width, y-130, -width , height , null);
                }
                break;
            default:
                if (facingRight) {
                    g2d.drawImage(frame, x, y, width, height, null);
                } else {
                    g2d.drawImage(frame, x + width, y, -width, height, null);
                }
        }
    }


    private void drawDebugInfo(Graphics2D g2d) {
        if (GameWindow.DEBUG_MODE) {
            g2d.setColor(Color.RED);
            g2d.draw(hitBox);
            if (attackBox != null) {
                g2d.setColor(Color.BLUE);
                g2d.draw(attackBox);
            }
        }
    }


    private float calculateScaleForState(FighterState state) {
        // 根据不同状态返回不同的缩放系数
        switch (state) {
            case ATTACK: return 1.5f;
            case JUMP: return 1.5f;
            case BLOCK: return 1.5f;
            default: return 1.5f;
        }
    }





    protected void drawHealthBar(Graphics2D g2d) {
        int barWidth = 80;
        int barHeight = 8;
        int barX = x + (width - barWidth) / 2;
        int barY = y - 20;

        // 背景
        g2d.setColor(Color.BLACK);
        g2d.fillRect(barX - 1, barY - 1, barWidth + 2, barHeight + 2);

        // 血量
        float healthPercent = (float)health / maxHealth;
        g2d.setColor(healthPercent > 0.5f ? Color.GREEN :
                healthPercent > 0.2f ? Color.YELLOW : Color.RED);
        g2d.fillRect(barX, barY, (int)(barWidth * healthPercent), barHeight);
    }

    // 角色控制方法
    public void moveLeft() {
        if (canMove()) {
            isDashing=false;
            x -= walkSpeed;
            facingRight = false;
            changeState(FighterState.WALK);
        }
    }

    public void moveRight() {
        if (canMove()) {
            isDashing=false;
            x += walkSpeed;
            facingRight = true;
            changeState(FighterState.WALK);
        }
    }

    public void jump() {
        if (isGrounded && canMove()) {
            yVelocity = jumpForce;
            isGrounded = false;
            changeState(FighterState.JUMP);
        }
    }

    public void attack() {
        if (canAttack()) {
            isDashing=false;
            changeState(FighterState.ATTACK);
        }
    }

    public void block() {
        if (canMove()) {
            isDashing=false;
            changeState(FighterState.BLOCK);
        }
    }

    // 快速冲刺(前进)
    public void dashForward() {
        if (canMove() && isGrounded) {
            isDashing = true;
            facingRight = true;
            changeState(FighterState.DASH);
        }
    }

    // 快速后退
    public void dashBackward() {
        if (canMove() && isGrounded) {
            isDashing = true;
            facingRight = false;
            changeState(FighterState.DASH);
        }
    }

    public void stopDash(){
        isDashing=false;
    }

    // 踢腿攻击
    public void kick() {
        if (canAttack()) {
            isDashing=false;
            changeState(FighterState.KICK);
        }
    }

    public boolean isAttackerInFront(Fighter attacker) {
        // 如果攻击者在右侧且自己面朝右，或者攻击者在左侧且自己面朝左
        return (attacker.getX() > this.x && this.facingRight) ||
                (attacker.getX() < this.x && !this.facingRight);
    }

    // 受击冷却机制
    private long lastHitTime;
    private static final long HIT_COOLDOWN = 300; // 300ms冷却

    public boolean canHit() {
        return System.currentTimeMillis() - lastHitTime > HIT_COOLDOWN;
    }

    public void recordHit() {
        lastHitTime = System.currentTimeMillis();
    }

    private long koStartTime = -1; // 记录倒下开始时间
    private static final long KO_DURATION = 3000; // 3秒延迟
    private List<HitEffect> hitEffects = new ArrayList<>();
    private boolean downFinished=false;

    public void takeHit(int damage, int hitX, int hitY ,Fighter attacker) {
        // 检查攻击是否来自背后
        boolean isFromBehind = attacker != null && !isAttackerInFront(attacker);

        if (currentState == FighterState.BLOCK && !isFromBehind && !isInvincible) {
            // 只有来自正面的攻击才能被格挡
            health -= damage / 20; // 格挡减少伤害
            changeState(FighterState.BLOCK);
            // 添加格挡特效
            // 添加带方向的格挡特效
            int effectX = facingRight ? x + width  : x - 20;
            hitEffects.add(new HitEffect("/effects/hit_blocked.gif", effectX-20, hitY, facingRight));

        } else if (currentState != FighterState.BLOCK || isFromBehind) {

            // 非格挡状态或来自背后的攻击
            if (!isInvincible) {
                for(int i=0;i<damage;i++){
                    health--;
                }
               // health -= damage;
                String hitEffectPath = getHitEffectPath();
                hitEffects.add(new HitEffect(hitEffectPath, hitX, hitY,facingRight));
                if(health<50&&!downFinished){ //若变为半血，倒地保护
                    changeState(FighterState.DOWN);
                    isInvincible=true;
                    isDown=true;
                    downStartTime= System.currentTimeMillis();
                    health--;
                    downFinished=true;

                }
                else if (health <= 0) {
                    health = 0;
                    changeState(FighterState.KO);
                    koStartTime = System.currentTimeMillis();
                }
                 else {
                    changeState(FighterState.HIT);
                }
            }
            if (currentState != FighterState.KO && currentState != FighterState.DOWN) { // 倒地状态不加受击效果
                hitEffects.add(new HitEffect(getHitEffectPath(), hitX, hitY,facingRight));
            }
        }
    }
    public boolean isKOFinished() {
        if (koStartTime == -1) return false;
        return System.currentTimeMillis() - koStartTime >= KO_DURATION;
    }

    public void resetKO() {
        koStartTime = -1;
    }

    private String getHitEffectPath() {
        // 可根据角色类型返回不同的受击效果
        return "/effects/hit_normal1.gif";
    }

    public void updateEffects() {
        // 移除已完成的效果
        hitEffects.removeIf(HitEffect::shouldRemove);

        // 更新所有活跃效果
        hitEffects.forEach(HitEffect::update);
    }

    public void drawEffects(Graphics2D g2d) {
        // 只绘制未播放完成的效果
        hitEffects.stream()
                .filter(effect -> !effect.shouldRemove())
                .forEach(effect -> effect.draw(g2d));
    }

    public void changeState(FighterState newState) {
        if (currentState != newState) {
            currentState = newState;
            playStateAnimation(newState);
        }
    }


    private String getAnimationPath(String filename) {
        return "/characters/" + getClass().getSimpleName().toLowerCase() + "/" + filename;
    }

    protected void playStateAnimation(FighterState state) {
        switch (state) {
            case IDLE:
                animation.play("IDLE");
                break;
            case WALK:
                animation.play("WALK");
                break;
            case JUMP:
                animation.play("JUMP");
                break;
            case ATTACK:
                animation.play("ATTACK");
                break;
            case BLOCK:
                animation.play("BLOCK");
                break;
            case HIT:
                animation.play("HIT");
                break;
            case KO:
                animation.play("KO");
                break;
            case DASH:
                animation.play("DASH");
                break;
            case KICK:
                animation.play("KICK");
                break;
            case DOWN:
                animation.play("DOWN");
                break;
        }
    }

    // 状态检查方法
    protected boolean canMove() {
        return currentState != FighterState.ATTACK &&
                currentState != FighterState.HIT &&
                currentState != FighterState.KO &&
                currentState != FighterState.BLOCK &&
                currentState != FighterState.KICK &&
                currentState != FighterState.DOWN; // 以上状态时不能移动;
    }

    protected boolean canAttack() {
        return currentState != FighterState.HIT &&
                currentState != FighterState.KO &&
                currentState != FighterState.ATTACK &&
                currentState != FighterState.KICK &&
                currentState != FighterState.DOWN; // 防止连续攻击;
    }

    // Getters
    public boolean isAttacking() {
        return currentState == FighterState.ATTACK
                //&& animation.getCurrentState().equals("ATTACK")
        ;
    }

    public boolean isAlive() {
        return health > 0;
    }

    public Rectangle2D getHitBox() {
        return hitBox;
    }

    public Rectangle2D getAttackBox() {
        return attackBox;
    }

    public void setX(int x) {
        this.x = x;
    }

    public void setY(int y) {
        this.y = y;
    }

    public FighterState getCurrentState() {
        return currentState;
    }

    public void setCurrentState(FighterState currentState) {
        this.currentState = currentState;
    }

    public int getHealth() {
        return health;
    }

    public void setHealth(int health) {
        this.health = health;
    }

    public String getName() {
        return name;
    }
}